package com.company.nuwa.common.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;

/**
 * <p>获取时间对应的显示维度</p>
 *
 * @author chengxiaobo
 * @version 1.0
 * @date 2020/09/27 09:46
 */
public interface DateUtils {

    String DATE_FORMAT = "yyyyMMdd";
    String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    String DEFAULT_DATETIME_FORMAT1 = "yyyyMMdd HH:mm:ss";
    String DEFAULT_DATETIME_SHORT16_FORMAT = "yyyy-MM-dd HH:mm";
    String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    String DEFAULT_MONTH_FORMAT = "yyyy-MM";
    String TIME_FORMAT = "HHmmss";
    /**
     * 一小时的秒数
     */
    int HOUR_SECOND = 60 * 60;
    /**
     * 一分钟的秒数
     */
    int MINUTE_SECOND = 60;
    /**
     * 日期格式
     */
    String DAY_FORMAT = "yyyy/MM/dd";
    /**
     * 日期正常格式
     */
    String NORM_DAY_FORMAT = "yyyy-MM-dd";
    /**
     * 月格式
     */
    String MONTH_FORMAT = "yyyy/MM";
    /**
     * 开始时间
     */
    String START_TIME = "startTime";
    /**
     * 结束时间
     */
    String END_TIME = "endTime";
    String START_PATTERN_END = "{0} ~ {1}";
    List<String> HOUR_LIST = Arrays.asList("00:00", "01:00", "02:00", "03:00", "04:00", "05:00", "06:00", "07:00",
            "08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00",
            "16:00", "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", "23:00");

    public static final java.time.format.DateTimeFormatter DF = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * Date类型转LocalDate类型
     *
     * @param date
     * @return
     */
    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDate();
    }

    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /***
     * description: LocalDateTime to String
     * @param date
     * @return java.lang.String
     */
    public static String localDateTimeToString(LocalDateTime date) {
        java.time.format.DateTimeFormatter dtf = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return date.format(dtf);
    }

    public static Date stringStamp2Date(String time) {
        time = time + "000";
        Long longTime = Long.valueOf(time);
        Date date = new Date(longTime);
        return date;
    }

    /**
     *
     **/
    public static String long2String(long time) {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time * 1000));
    }

    /**
     * 将时间转换为时间戳
     */
    public static long dateToStamp(String s) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(s);
        return date.getTime();
    }

    /**
     * 将时间戳转换为时间
     */
    public static String stampToDate(String s) {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt =  Long.parseLong(s);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }

    /**
     *
     **/
    public static Date string2Date(String time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = format.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    public static Date stringToDate(String date) throws ParseException {
        return new SimpleDateFormat("yyyy-MM-dd").parse(date);
    }

    public static Integer dateToInteger(LocalDate localDate) {
        return Integer.valueOf(localDate.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd")));
    }

    public static Integer dateToInteger(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        return Integer.valueOf(format.format(date));
    }

    public static Integer dateToMonth(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
        return Integer.valueOf(format.format(date));
    }

    public static Integer dateToYear(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        return Integer.valueOf(format.format(date));
    }


    public static Date getDateMonthStart(Date date) {
        // 获取当月第一天
        Calendar cale = Calendar.getInstance();
        cale.setTime(date);
        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);
        //设置小时数，24小时制
        cale.set(Calendar.HOUR_OF_DAY, 0);
        cale.set(Calendar.MINUTE, 0);
        cale.set(Calendar.SECOND, 0);
        return cale.getTime();
    }

    public static Date getDateMonthEnd(Date date) {
        Calendar cale = Calendar.getInstance();
        cale.setTime(date);
        cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 1);
        cale.set(Calendar.DAY_OF_MONTH, 0);
        //设置小时数，24小时制
        cale.set(Calendar.HOUR_OF_DAY, 23);
        cale.set(Calendar.MINUTE, 59);
        cale.set(Calendar.SECOND, 59);
        return cale.getTime();
    }

    public static Date getDateStart(Date date) {
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(date);
        //设置小时数，24小时制
        startCalendar.set(Calendar.HOUR_OF_DAY, 0);
        startCalendar.set(Calendar.MINUTE, 0);
        startCalendar.set(Calendar.SECOND, 0);
        return startCalendar.getTime();
    }

    public static Date getDateEnd(Date date) {
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(date);
        //设置小时数，24小时制
        startCalendar.set(Calendar.HOUR_OF_DAY, 23);
        startCalendar.set(Calendar.MINUTE, 59);
        startCalendar.set(Calendar.SECOND, 59);
        return startCalendar.getTime();
    }

    /**
     * 将时间转换为时间戳
     */
    public static Date integerToDate(Integer s) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        return simpleDateFormat.parse(String.valueOf(s));
    }

    /**
     * 获取两个工作日之间的日期
     *
     * @param start yyyyMMdd
     * @param end   yyyyMMdd
     * @return List<Date>
     */
    public static Set<Date> getBetweenDates(int start, int end) {
        Date startDate = getCurrentWorkDate(getLocalWorkDate(start));
        Date endDate = getCurrentWorkDate(getLocalWorkDate(end));
        Set<Date> result = new HashSet<>();
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(startDate);
        tempStart.add(Calendar.DAY_OF_YEAR, 1);
        Calendar tempEnd = Calendar.getInstance();
        tempEnd.setTime(endDate);
        while (tempStart.before(tempEnd)) {
            result.add(tempStart.getTime());
            tempStart.add(Calendar.DAY_OF_YEAR, 1);
        }
        result.add(startDate);
        result.add(endDate);
        return result;
    }

    /**
     * LocalDate to Date
     *
     * @param localDate java8 Date
     * @return Date
     */
    public static Date getCurrentWorkDate(LocalDate localDate) {
        Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();

        return Date.from(instant);
    }

    /**
     * yyyyMMdd to  LocalDate
     *
     * @param workDay 工作日
     * @return LocalDate
     */
    public static LocalDate getLocalWorkDate(int workDay) {
        return LocalDate.of(workDay / 1_000_0, (workDay - workDay / 1_000_0 * 1_000_0) / 1_00,
                workDay - workDay / 1_00 * 1_00);
    }

    /**
     * 根据秒数获取时间串
     *
     * @param second (eg: 100s)
     * @return (eg : 00 : 01 : 40)
     */
    static String getTimeStrBySecond(int second) {
        if (second <= 0) {
            return "00:00:00";
        }

        //StringBuilder sb = new StringBuilder();
        int hours = second / HOUR_SECOND;
        if (hours > 0) {
            second -= hours * HOUR_SECOND;
        }

        int minutes = second / MINUTE_SECOND;
        if (minutes > 0) {
            second -= minutes * MINUTE_SECOND;
        }

        return (hours >= 10 ? (hours + "")
                : ("0" + hours) + ":" + (minutes >= 10 ? (minutes + "") : ("0" + minutes)) + ":"
                + (second >= 10 ? (second + "") : ("0" + second)));
    }


    /**
     * @param nowTime   当前时间
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return
     * @author sunran   判断当前时间在时间区间内
     */
    static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String sNow = sdf.format(nowTime);
            String sStart = sdf.format(startTime);
            String sEnd = sdf.format(endTime);
            Date dateNow = sdf.parse(sNow);
            Date dateStart = sdf.parse(sStart);
            Date dateEnd = sdf.parse(sEnd);

            return dateNow.compareTo(dateStart) >= 0 && dateNow.compareTo(dateEnd) <= 0;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据开始时间和结束时间返回对应的区间范围（日）
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param isDesc    是否需要倒序
     * @return 时间范围
     */
    static List<String> rangeDayDimension(Date startTime, Date endTime, Boolean isDesc, String format) {
        List<String> resultList = Lists.newArrayList();
        Calendar calendar = Calendar.getInstance();
        // 设置开始时间
        calendar.setTime(startTime);

        while (!calendar.getTime().after(endTime)) {
            resultList.add(DateUtil.format(calendar.getTime(), format));
            calendar.add(Calendar.DAY_OF_YEAR, 1);
        }
        if (isDesc) {
            Collections.reverse(resultList);
        }
        return resultList;
    }

    static List<String> rangeDayDimension(Date startTime, Date endTime, Boolean isDesc) {
        return rangeDayDimension(startTime, endTime, isDesc, DAY_FORMAT);
    }

    /**
     * 根据开始时间和结束时间获取对应的区间范围（周）
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param dates     传入对象 List
     */
    static void rangeWeekDimension(Date startDate, Date endDate, List<List<String>> dates, String dayFormat) {
        // 1、设置开始时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        // 2、获取一完整周的开始时间
        while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
            calendar.add(Calendar.DAY_OF_WEEK, -1);
        }
        List<String> list = Lists.newArrayList();
        for (int i = 0; i < 7; i++) {
            list.add(DateUtil.format(calendar.getTime(), dayFormat));
            calendar.add(Calendar.DATE, 1);
        }
        dates.add(list);
        Date rollBack = calendar.getTime();
        // 3、递归获取结束时间对应的时间范围
        if (!endDate.before(rollBack)) {
            rangeWeekDimension(rollBack, endDate, dates, dayFormat);
        }
    }

    static void rangeWeekDimension(Date startDate, Date endDate, List<List<String>> dates) {
        rangeWeekDimension(startDate, endDate, dates, DAY_FORMAT);
    }


    /**
     * 根据开始时间和结束时间获取对应的区间范围（月）
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param monthList 月份 List
     */
    static void rangeMonthDimension(Date startDate, Date endDate, List<String> monthList) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        do {
            monthList.add(DateUtil.format(calendar.getTime(), MONTH_FORMAT));
            calendar.add(Calendar.MONTH, 1);
        } while (endDate.after(calendar.getTime()));
    }

    /**
     * 根据开始时间和结束时间获取对应的区间范围（月）
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @param dates     对应的日期 List
     */
    static void rangeMonthDetailDimension(Date startDate, Date endDate, List<List<String>> dates, String dayFormat) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        do {
            List<String> dayList = Lists.newArrayList();
            int end = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            for (int i = 1; i <= end; i++) {
                dayList.add(DateUtil.format(calendar.getTime(), dayFormat));
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
            dates.add(dayList);
        } while (!endDate.before(calendar.getTime()));
    }

    static void rangeMonthDetailDimension(Date startDate, Date endDate, List<List<String>> dates) {
        rangeMonthDetailDimension(startDate, endDate, dates, DAY_FORMAT);
    }

    /**
     * 拼接月份的开始时间和结束时间
     *
     * @param month 月份
     * @return 月初到月尾的拼接
     */
    static String rangeMonth(Date month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(month);

        String stringBuilder = month + "/01~" + month +
                "/" + calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        return stringBuilder;
    }

    /**
     * 根据开始时间和结束时间获取对应的开始时间和结束时间
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 返回最大的开始时间和结束时间
     */
    static Map<String, Date> rangeWeekDimensionReturn(Date startDate, Date endDate) {
        // 获取对应的数据集合
        List<List<String>> dates = Lists.newArrayList();
        rangeWeekDimension(startDate, endDate, dates);
        Map<String, Date> resultMap = Maps.newHashMap();
        if (CollUtil.isNotEmpty(dates)) {
            resultMap.put(START_TIME, DateUtil.parse(dates.get(0).get(0)));
            List<String> last = dates.get(dates.size() - 1);
            resultMap.put(END_TIME, DateUtil.parse(last.get(6) + " 23:59:59"));
        }
        return resultMap;
    }

    /**
     * 根据开始时间和结束时间获取对应的开始时间和结束时间
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 返回最大的开始时间和结束时间
     */
    static Map<String, Date> rangeMonthDimensionReturn(Date startDate, Date endDate) {
        // 获取对应的数据集合
        List<List<String>> dates = Lists.newArrayList();
        rangeMonthDetailDimension(startDate, endDate, dates);
        Map<String, Date> resultMap = Maps.newHashMap();
        if (CollUtil.isNotEmpty(dates)) {
            resultMap.put(START_TIME, DateUtil.parse(dates.get(0).get(0)));
            List<String> last = dates.get(dates.size() - 1);
            resultMap.put(END_TIME, DateUtil.parse(last.get(last.size() - 1) + " 23:59:59"));
        }
        return resultMap;
    }


    /**
     * 根据 date 获取对应的日维度
     *
     * @param date 日期
     * @return 按照规则返回对应的日期 List
     */
    static List<String> dayDimension(Date date) {
        List<String> resultList = Lists.newArrayList();
        // 1、添加当天记录
        resultList.add(DateUtil.format(date, DAY_FORMAT));
        // 2、设置为当前时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 3、添加对应的 2~7 维度
        for (int i = 1; i <= 6; i++) {
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            resultList.add(DateUtil.format(calendar.getTime(), DAY_FORMAT));
        }

        // 4、添加第 15 和 30 天
        calendar.add(Calendar.DAY_OF_MONTH, 8);
        resultList.add(DateUtil.format(calendar.getTime(), DAY_FORMAT));
        calendar.add(Calendar.DAY_OF_MONTH, 15);
        resultList.add(DateUtil.format(calendar.getTime(), DAY_FORMAT));
        return resultList;
    }

    /**
     * 根据 date 获取对应的周维度
     *
     * @param date 日期
     * @return 按照规则返回对应的周 List
     */
    static List<Map<String, String>> weekDimension(Date date) {
        List<Map<String, String>> resultList = Lists.newArrayList();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.WEEK_OF_YEAR, 1);
        // 1、添加第 1 周记录
        Map<String, String> firstWeekMap = Maps.newHashMap();
        firstWeekMap.put(START_TIME, DateUtil.format(date, DAY_FORMAT));
        firstWeekMap.put(END_TIME, DateUtil.format(calendar.getTime(), DAY_FORMAT));

        // 3、添加对应的 2~9 周维度
        String startTime;
        String endTime;
        for (int i = 1; i <= 7; i++) {
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            startTime = DateUtil.format(calendar.getTime(), DAY_FORMAT);
            calendar.add(Calendar.WEEK_OF_YEAR, 1);
            endTime = DateUtil.format(calendar.getTime(), DAY_FORMAT);
            Map<String, String> map = Maps.newHashMap();
            map.put(START_TIME, startTime);
            map.put(END_TIME, endTime);
            resultList.add(map);
        }
        return resultList;
    }

    /**
     * 根据 date 获取对应的月维度
     *
     * @param date 日期
     * @return 按照规则返回对应的月 List
     */
    static List<Map<String, String>> monthDimension(Date date) {
        List<Map<String, String>> resultList = Lists.newArrayList();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        // 1、添加第 1 周记录
        Map<String, String> firstWeekMap = Maps.newHashMap();
        firstWeekMap.put(START_TIME, DateUtil.format(date, DAY_FORMAT));
        firstWeekMap.put(END_TIME, DateUtil.format(calendar.getTime(), DAY_FORMAT));

        // 3、添加对应的 2~9 周维度
        String startTime;
        String endTime;
        for (int i = 1; i <= 7; i++) {
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            startTime = DateUtil.format(calendar.getTime(), DAY_FORMAT);
            calendar.add(Calendar.MONTH, 1);
            endTime = DateUtil.format(calendar.getTime(), DAY_FORMAT);
            Map<String, String> map = Maps.newHashMap();
            map.put(START_TIME, startTime);
            map.put(END_TIME, endTime);
            resultList.add(map);
        }
        return resultList;
    }

    /**
     * 通过固定格式拼接开始时间和结束时间
     *
     * @param startTime
     * @param endTime
     * @return 拼接后的字符串
     */
    static String splicing(String startTime, String endTime) {
        return MessageFormat.format(START_PATTERN_END, startTime, endTime);
    }

    /**
     * 获取当前日期 yyyyMMdd
     *
     * @return
     */
    static String CurrentDate() {
        return getCurrentDateTime(DATE_FORMAT);
    }

    /**
     * 获取当前时间
     *
     * @param fmt 输出格式
     * @return
     */
    static String getCurrentDateTime(String fmt) {
        if (fmt == null) {
            fmt = DEFAULT_DATETIME_FORMAT;
        }
        return getDateTime(null, fmt);
    }

    /**
     * 根据 毫秒数及格式化信息，输入当前时间
     *
     * @param time
     * @param fmt
     * @return
     */
    static String getDateTime(Long time, String fmt) {
        if (fmt == null) {
            fmt = DEFAULT_DATETIME_FORMAT;
        }
        if (time != null) {
            return new DateTime(time).toString(fmt);
        } else {
            return new DateTime().toString(fmt);
        }
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    static String CurrentTime() {
        return getDateTime(null, TIME_FORMAT);
    }

    static Date LocalDateToUdate(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        Date date = Date.from(instant);
        return date;
    }

    /**
     * 获取昨天的日期，返回的是 yyyyMMdd
     *
     * @return
     */
    static String Yesterday() {
        return new DateTime().minusDays(1).toString(DATE_FORMAT);
    }

    /**
     * 间隔天数
     *
     * @param startTime
     * @param endTime
     * @return
     */
    static Long between(Long startTime, Long endTime) {
        return Math.abs(startTime / (24 * 60 * 60 * 1000) - endTime / (24 * 60 * 60 * 1000));
    }

    /**
     * 判断是否是今天的日期
     *
     * @param time
     * @return
     */
    static Boolean checkToday(Long time) {
        return getDateTime(time, "yyyy-MM-dd").equals(getCurrentDate());
    }

    /**
     * 获取当前日期
     *
     * @return
     */
    static String getCurrentDate() {
        return getCurrentDateTime(DEFAULT_DATE_FORMAT);
    }

    /**
     * 判断是否是昨天的日期
     *
     * @param time
     * @return
     */
    static Boolean checkYesterday(Long time) {
        return getDateTime(time, "yyyy-MM-dd") == getYesterday();
    }

    /**
     * 获取昨天的日期，返回的是 yyyy-MM-dd
     *
     * @return
     */
    static String getYesterday() {
        return new DateTime().minusDays(1).toString(DEFAULT_DATE_FORMAT);
    }

    /**
     * 开始日期与结束日期的每个日期
     */
    static List<String> findDates(Date dBegin, Date dEnd) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        List<String> lDate = new ArrayList<>();
        //lDate.add(dBegin);
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        lDate.add(format.format(dBegin.getTime()));
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            String enddate = format.format(calBegin.getTime());
            // System.out.println("=="+enddate);
            lDate.add(enddate);
        }
        return lDate;
    }

    /**
     * 开始日期与结束日期的每个月份
     */
    static List<String> findYesrs(Date dBegin, Date dEnd) throws ParseException {
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(sdf.parse(sdf.format(dBegin)));
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(sdf.parse(sdf.format(dEnd)));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        Calendar curr = min;
        while (curr.before(max)) {
            result.add(sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }
        return result;
    }

    /**
     * 获取上个月的今天日期
     *
     * @param fmt
     * @return
     */
    static String getBeforeMonthDate(String fmt) {
        if (fmt == null) {
            fmt = DEFAULT_DATE_FORMAT;
        }
        return new DateTime().minusDays(1).toString(fmt);
    }

    /**
     * 获取前天的日期，返回的是 yyyy-MM-dd
     *
     * @return
     */
    static String getBeforeYesterday() {
        return new DateTime().minusDays(2).toString(DEFAULT_DATE_FORMAT);
    }

    /**
     * 获取当前年月
     *
     * @return
     */
    static String getCurrent() {
        return getCurrentDateTime(DEFAULT_MONTH_FORMAT);
    }

    /**
     * 获取今天开始0点时间
     *
     * @return
     */
    static Long getCurrentDateFirst() {
        return new DateTime().withMillisOfDay(0).getMillis();
    }

    /**
     * 获取今天最后一毫秒时间
     *
     * @return
     */
    static Long getCurrentDateLast() {
        return new DateTime().withHourOfDay(23).withMinuteOfHour(59).withSecondOfMinute(59)
                .getMillis() + 999;
    }

    /**
     * 获取当前时间，输出格式yyyy-MM-dd HH:mm:ss
     *
     * @return
     */
    static String getCurrentDateTime() {
        return getCurrentDateTime(DEFAULT_DATETIME_FORMAT);
    }

    /**
     * 获取当前毫秒数 yyyy-MM-dd
     *
     * @return
     */
    static Long getCurrentTime() {
        return System.currentTimeMillis();
    }

    /**
     * 获取当前传入 日期的毫秒
     *
     * @param strDate
     * @return
     */
    static Long getDate(String strDate) {
        if (strDate != null) {
            return formatDateTime(strDate, null);
        } else {
            return null;
        }
    }

    static Long formatDateTime(String dateTime, String fmt) {
        if (dateTime == null) {
            return null;
        }
        dateTime = dateTime.trim();
        if (fmt == null) {
            switch (dateTime.length()) {
                case 5:
                    // 5位是 MM-dd格式，需要进行补位，默认情况下面，
                    String yyyyMMdd = getDateTime(null, DEFAULT_DATE_FORMAT);
                    String[] cDay = yyyyMMdd.split("-");

                    String[] hDay = dateTime.split("-");
                    // 当前的月份 大于 传入的时间月份的时候，默认设置为 传入的时间是今年
                    if ((Integer.parseInt(cDay[1])) >= (Integer.parseInt(hDay[0]))) {
                        dateTime = cDay[0] + "-" + dateTime;
                    } else { // 反之，传入的时间是去年的
                        dateTime = (Integer.parseInt(cDay[0])) + "-" + dateTime;
                    }
                    fmt = DEFAULT_DATE_FORMAT;
                    break;
                case 8:
                    fmt = DATE_FORMAT;
                    break;
                case 10:
                    fmt = DEFAULT_DATE_FORMAT;
                    break;
                case 16:
                    fmt = DEFAULT_DATETIME_SHORT16_FORMAT;
                    break;
                default:
                    fmt = DEFAULT_DATETIME_FORMAT;
                    break;
            }
        }
        DateTimeFormatter format = DateTimeFormat.forPattern(fmt);
        return DateTime.parse(dateTime, format).getMillis();
    }

    /**
     * 获取当前传入 日期的 00:00:00 毫秒
     *
     * @param strDate 格式 yyyy-MM-dd
     * @return
     */
    static Long getDateFirst(String strDate) {
        if (strDate != null) {
            if (strDate.length() != 10) {
                return null;
            }
            return formatDateTime(strDate + " 00:00:00", null);
        } else {
            return null;
        }
    }

    /**
     * 获取当前传入 日期的 00:00:00 毫秒
     *
     * @param strDate 格式 yyyyMMdd
     * @return
     */
    static Long getDateFirst1(String strDate) {
        if (strDate != null) {
            DateTimeFormatter format = DateTimeFormat.forPattern(DEFAULT_DATETIME_FORMAT1);
            return DateTime.parse(strDate + " 00:00:00", format).getMillis();
        } else {
            return null;
        }
    }

    /**
     * 获取当前传入 日期的 00:00:00 毫秒
     *
     * @param strDate 格式 yyyy-MM-dd
     * @return
     */
    static Long getDateFirsts(String strDate) {
        if (strDate != null) {
            if (strDate.length() != 10) {
                return null;
            }
            return formatDateTime(strDate + " 23:59:59", null);
        } else {
            return null;
        }
    }

    /**
     * 获取当前传入 日期的 23:59:59 毫秒
     *
     * @param strDate 格式 yyyyMMdd
     * @return
     */
    static Long getDateLast1(String strDate) {
        if (strDate != null) {
            DateTimeFormatter format = DateTimeFormat.forPattern(DEFAULT_DATETIME_FORMAT1);
            return DateTime.parse(strDate + " 23:59:59", format).getMillis();
        } else {
            return null;
        }
    }

    /**
     * 根据 毫秒数格式化日期
     *
     * @return yyyyMMdd
     */
    static String getDateStr() {
        return getCurrentDateTime(DATE_FORMAT);
    }

    /**
     * 根据 毫秒数格式化日期
     *
     * @param time
     * @param fmt
     * @return
     */
    static String getDateTimeStr(Long time, String fmt) {
        if (fmt == null) {
            fmt = DEFAULT_DATETIME_FORMAT;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(fmt);
        if (time != null) {
            return simpleDateFormat.format(time);
        } else {
            return null;
        }
    }

    /**
     * 两个时间相差距离多少天多少小时多少分多少秒
     *
     * @return String 返回值为：xx天xx小时xx分xx秒
     */
    static String getDistanceTime(long time1, long time2) {

        long day = 0;
        long hour = 0;
        long min = 0;
        long sec = 0;
        try {

            long diff;
            if (time1 < time2) {
                diff = time2 - time1;
            } else {
                diff = time1 - time2;
            }
            day = diff / (24 * 60 * 60 * 1000);
            hour = (diff / (60 * 60 * 1000) - day * 24);
            min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
            sec = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String messageTime = "";
        if (day >= 1) {
            messageTime = day + "天前";
        } else if (hour < 24 && hour > 0) {
            messageTime = hour + "小时前";
        } else if (min < 60 && min > 0) {
            messageTime = min + "分钟前";
        } else if (sec < 60) {
            messageTime = "刚刚";
        }
        return messageTime;
        // return day + "天" + hour + "小时" + min + "分" + sec + "秒";
    }

    /**
     * 两个时间相差距离多少天
     */
    static String getDistanceTimeDay(long time1, long time2) {

        long day = 0;

        try {

            long diff;
            if (time1 < time2) {
                diff = time2 - time1;
            } else {
                diff = time1 - time2;
            }
            day = diff / (24 * 60 * 60 * 1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String messageTime = "1";
        if (day >= 1) {
            messageTime = day + "";
        }
        return messageTime;
        // return day + "天" + hour + "小时" + min + "分" + sec + "秒";
    }

    /**
     * 获取指定 时间的下N天
     * 如果 time不传递，将获取今天的下N天
     *
     * @param time
     * @param fmt
     * @return
     * @prarm step
     */
    static String getNextDate(Long time, String fmt, Integer step) {
        if (fmt == null) {
            fmt = DEFAULT_DATE_FORMAT;
        }

        if (time != null) {
            return new DateTime(time).plusDays(step).toString(fmt);
        } else {
            return new DateTime().plusDays(step).toString(fmt);
        }
    }

    /**
     * 获取指定 时间的下N天，返回毫秒数
     * 如果 time不传递，将获取今天的下N天
     *
     * @param time
     * @return
     * @prarm step
     */
    static Long getNextDate(Long time, Integer step) {
        if (time != null) {
            return new DateTime(time).plusDays(step).getMillis();
        } else {
            return new DateTime().plusDays(step).getMillis();
        }
    }

    /**
     * 获取当前月日
     *
     * @return
     */
    static String getNowTime() {
        Calendar now = Calendar.getInstance();
        String time = (now.get(Calendar.MONTH) + 1) + "月" + now.get(Calendar.DAY_OF_MONTH) + "日";
        return time;
    }

    /**
     * 获取上周昨天的日期，返回的是 yyyy-MM-dd
     *
     * @return
     */
    static String getWeekYesterday() {
        return new DateTime().minusDays(8).toString(DEFAULT_DATE_FORMAT);
    }

    /**
     * 获取昨天的 00:00:00 毫秒
     *
     * @return
     */
    static Long getYesterdayFirst() {
        return new DateTime().minusDays(1).withMillisOfDay(0).getMillis();
    }

    /**
     * 获取昨天的 23:59:59 毫秒
     *
     * @return
     */
    static Long getYesterdayLast() {
        return new DateTime().minusDays(1).withHourOfDay(23).withMinuteOfHour(59)
                .withSecondOfMinute(59).getMillis();
    }

    static void main(String[] args) throws ParseException {
        String minDate = "2019-01";
        String maxDate = "2019-09";
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(sdf.parse(minDate));
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(sdf.parse(maxDate));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        Calendar curr = min;
        while (curr.before(max)) {
            result.add(sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }
        System.out.println(result);
    }

    /**
     * 日期格式化成字符串
     *
     * @param date
     * @param fmt
     * @return
     * @throws Exception
     */
    static Date strFormatDate(String date, String fmt) throws Exception {
        SimpleDateFormat myFormat = new SimpleDateFormat(fmt);
        return myFormat.parse(date);
    }

    static Date localDateTime2Date(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }
}
